/** main container to all dialogs within the plugin, dialogs */

package ij.hkust.QuickPALM;

import ij.*;
import ij.io.*;
import ij.measure.*;
import ij.plugin.*;
import ij.plugin.filter.*;
import ij.plugin.frame.*;
import ij.process.*;
import ij.gui.*;
import ij.measure.CurveFitter.*;

import java.awt.*;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.BufferedReader;

public class MyDialogs
{


	// Camera settings
	String EMSwitch;
	String [] EMSwitchOpts = new String [2];
	
	int EMGain = 1;
	double preAmp = 5.1;
	
	String Output_Amplifier;
	String [] OAOpts = new String [2];
	
	String Trigger;
	String [] TriggerOpts = new String [3];
	
	double Exposure;
	double Magnification;
	
	public String STORMPath;
	
	
	//
	public boolean run;	

	public int roixs;
	public int roixe;
	public int roiys;
	public int roiye;
	public boolean processROI = false;

	public boolean Multicolor;
	public int Colors;

	ImagePlus imp;
	RoiManager rmanager;
	Roi [] rois;

	ij.Prefs prefs = new ij.Prefs(); 

	java.lang.String ptablefile;

	int width;
	int height;
	int nslices;
	String imtitle;
	int nrois;

	public int snr;
	public double pixelsize;

	public boolean cusfwhm;
	public double fwhm;
	//int roirad;
	double pthrsh = 0.2;
	boolean smartsnr;

	int buffer;
	double cal_z;
	int window;
	public double magn;

	// advanced settings
	double minsize;
	double maxsize;
	double symmetry = 50;
	int maxpart = 1000; //maximum particles
	public int threads = 50;//the max threads count
	boolean saveToFile;
	public double RImagePSize;

	// used on calib
	java.lang.String model;
	java.lang.String [] models = new java.lang.String[5]; // used for the calibration
	boolean part_divergence;
	boolean part_extrainfo;

	// used on is3d
	public boolean is3d;
	public java.lang.String calfile;

	// used on view
	public boolean view;
	public int viewer_accumulate;
	public int viewer_update;
	public double saturation;

	// used on attach
	boolean attach;
	java.lang.String imagedir;
	java.lang.String pattern;
	java.lang.String prefix;
	java.lang.String sufix;
	int nimchars;
	int nimstart;
	int waittime;

	// Reconstruct interface vars
	public double viewer_tpixelsize;
	public int viewer_owidth;
	public int	viewer_oheight;
	public double redValue;
	public double greenValue;
	public double blueValue;
	//double saturation;

	public java.lang.String [] view_modes = new java.lang.String[6];
	public java.lang.String view_mode;
	public boolean viewer_doConvolve;
	//boolean viewer_doBW;
	public boolean viewer_do3d;
	public boolean viewer_doMovie;
	//boolean viewer_doSave;

	public double viewer_mergeabove;
	public double viewer_mergebellow;

	public double viewer_fwhm;
	public boolean viewer_is8bit;
	public double viewer_zstep;
	//int viewer_update;
	//int viewer_accumulate;
	
	public long pulse_duration = (long)prefs.get("QuickPALM.pulse_duration", 50);//AOTF
	public long pulse_separation = (long)prefs.get("QuickPALM.pulse_separation", 500);//AOTF
	
	public String power_656 = prefs.get("QuickPALM.power_656", "4000");//AOTF
	public String power_561 = prefs.get("QuickPALM.power_561", "4000");//AOTF
	public String power_488 = prefs.get("QuickPALM.power_488", "4000");;//AOTF
	public String power_405 = prefs.get("QuickPALM.power_405", "4000");;//AOTF
	
	boolean pulse_stop=true;


	// Data members for drawer
	java.lang.String[] drawer_modes = new java.lang.String[2];
	java.lang.String drawer_mode;
	public int drawer_owidth;
	public int drawer_oheight;
	public boolean drawer_cusres;
	public double drawer_minpsize;
	public double drawer_psize;
	public double drawer_magn;
	public int drawer_nframe;
	public double drawer_NA;

	public double drawer_noise;
	public double drawer_max;
	public double drawer_peakdev;	
	public double drawer_intensity;

	double drawer_radius;

	boolean sim_open;

	boolean sim_virtual;
	java.lang.String[] sim_modes = new java.lang.String[2];
	java.lang.String sim_mode;
	java.lang.String[] sim_objs = new java.lang.String[2];
	java.lang.String sim_obj;
	double sim_minpsize;
	double sim_magn;
	double sim_prob;
	double sim_dis;
	double sim_mindis;

	boolean sim_climg = false;
	double sim_campsize; 
	int sim_clwidth;
	int sim_clheight;


	public boolean getImageDirectory()
	{
		DirectoryChooser chooser = new DirectoryChooser("Choose directory to process");
		imagedir = chooser.getDirectory();
		return true;
	}

	public boolean getCalibrationFile()
	{
		java.lang.String cal_dir = prefs.get("QuickPALM.cal_dir", ".");
		java.lang.String cal_file = prefs.get("QuickPALM.cal_file", "Astigmatism calibration.xls");
		OpenDialog chooser = new OpenDialog("Astigmatism calibration", cal_dir, cal_file);
		calfile = chooser.getDirectory()+chooser.getFileName();
		prefs.set("QuickPALM.cal_dir", chooser.getDirectory());
		prefs.set("QuickPALM.cal_file", chooser.getFileName());
		return true;
	}

	public boolean getParticlesTableFile()
	{
		java.lang.String ptable_dir = prefs.get("QuickPALM.ptable_dir", ".");
		java.lang.String ptable_file = prefs.get("QuickPALM.ptable_file", "Particles Table.xls");
		OpenDialog chooser = new OpenDialog("Load Particles Table", ptable_dir, ptable_file);
		ptablefile = chooser.getDirectory()+chooser.getFileName();
		prefs.set("QuickPALM.ptable_dir", chooser.getDirectory());
		prefs.set("QuickPALM.ptable_file", chooser.getFileName());
		return true;
	}

	public boolean checkBeads() {
		rmanager=RoiManager.getInstance();
		if (IJ.versionLessThan("1.26i"))
			return false;
		else if (rmanager==null)
		{
			IJ.error("Add bead ROIs to the RoiManager first (select region then press [t]).");
			return false;	
		}

		nrois = rmanager.getCount();
		if (nrois==0)
		{
			IJ.error("Add bead ROIs to the RoiManager first (select region then press [t]).");
			return false;
		}
		rois = rmanager.getRoisAsArray();
		return true;
	}

	public boolean checkDrift() {
		rmanager=RoiManager.getInstance();
		if (IJ.versionLessThan("1.26i"))
			return false;
		else if (rmanager==null)
		{
			IJ.error("Add ROIs to use in drift correction to the RoiManager first (select region then press [t]).");
			return false;	
		}
		nrois = rmanager.getCount();
		if (nrois==0)
		{
			IJ.error("Add ROIs to use in drift correction to the RoiManager first (select region then press [t]).");
			return false;
		}
		rois = rmanager.getRoisAsArray();
		return true;
	}


	public boolean checkResolution() {
		rmanager=RoiManager.getInstance();
		if (IJ.versionLessThan("1.26i"))
			return false;
		else if (rmanager==null)
		{
			IJ.error("Add ROIs to use in resolution estimation to the RoiManager first (select region then press [t]).");
			return false;	
		}
		nrois = rmanager.getCount();
		if (nrois==0)
		{
			IJ.error("Add ROIs to use in resolution estimation to the RoiManager first (select region then press [t]).");
			return false;
		}
		rois = rmanager.getRoisAsArray();
		return true;
	}

	public boolean beadCalibration3d() {
		imp = IJ.getImage();
		if (imp==null)
		{
			IJ.noImage();
			return false;
		}
		else if (imp.getStackSize() == 1) 
		{
			IJ.error("Stack required");
			return false;
		} 
		else if (imp.getType() != ImagePlus.GRAY8 && imp.getType() != ImagePlus.GRAY16 ) 
		{
			// In order to support 32bit images, pict[] must be changed to float[], and  getPixel(x, y); requires a Float.intBitsToFloat() conversion
			IJ.error("8 or 16 bit greyscale image required");
			return false;
		}
		width=imp.getWidth();
		height=imp.getHeight();
		nslices=imp.getStackSize();
		imtitle = imp.getTitle();

		models[0]="*None*";
		models[1]="line";
		models[2]="2nd degree polynomial";
		models[3]="3rd degree polynomial";
		models[4]="4th degree polynomial";

		GenericDialog gd = new GenericDialog("3D STORM calibration");
		gd.addNumericField("Maximum FWHM (in px)", prefs.get("QuickPALM.3Dcal_fwhm", 20), 0);
		gd.addNumericField("Particle local threshold (% maximum intensity)", prefs.get("QuickPALM.pthrsh", 20), 0);
		gd.addNumericField("Z-spacing (nm)", prefs.get("QuickPALM.z-step", 10), 2);
		gd.addNumericField("Calibration Z-smoothing (radius)", prefs.get("QuickPALM.window", 1), 0);
		gd.addChoice("Model", models, prefs.get("QuickPALM.model", models[3]));
		gd.addCheckbox("Show divergence of bead positions against model", prefs.get("QuickPALM.3Dcal_showDivergence", false));
		gd.addCheckbox("Show extra particle info", prefs.get("QuickPALM.3Dcal_showExtraInfo", false));
		gd.addMessage("\n\nDon't forget to save the table in the end...");
		gd.showDialog();
		if (gd.wasCanceled())
			return false;
		fwhm = gd.getNextNumber();
		prefs.set("QuickPALM.QuickPALM.3Dcal_fwhm", fwhm);
		pthrsh = gd.getNextNumber()/100;
		prefs.set("QuickPALM.pthrsh", pthrsh*100);
		cal_z = gd.getNextNumber();
		prefs.set("QuickPALM.z-step", cal_z);
		window = (int) gd.getNextNumber();
		prefs.set("QuickPALM.window", window);
		model = gd.getNextChoice();
		prefs.set("QuickPALM.model", model);
		part_divergence = gd.getNextBoolean();
		prefs.set("QuickPALM.3Dcal_showDivergence", part_divergence);
		part_extrainfo = gd.getNextBoolean();
		prefs.set("QuickPALM.3Dcal_showExtraInfo", part_extrainfo);
		return true;
	}

	public boolean writeReconstructDataset() {
		view_modes[0]="3D color";
		view_modes[1]="2D histogram";
		view_modes[2]="2D particle intensity (16-bit)";
		view_modes[3]="2D particle intensity (8-bit)";
		view_modes[4]="2D multicolor";
		view_modes[5]="custom colors";

		GenericDialog gd = new GenericDialog("Reconstruct PALM/STORM Dataset");
		gd.addNumericField("Target pixel size for the rendered image (nm)", prefs.get("QuickPALM.viewer_tpixelsize", 30), 2);
		gd.addNumericField("Original image width (px)", prefs.get("QuickPALM.viewer_owidth", 512), 2);
		gd.addNumericField("Original image height (px)", prefs.get("QuickPALM.viewer_oheight", 512), 2);
		gd.addChoice("View mode", view_modes, prefs.get("QuickPALM.view_mode", view_modes[1]));
		//gd.addNumericField("Allow image saturation (%)", prefs.get("QuickPALM.saturation", 50), 0);

		gd.addCheckbox("Simulate sub-difraction spot (gaussian convolution - only 2D)", prefs.get("QuickPALM.viewer_doConvolve", true));
		//gd.addCheckbox("Make 3D stack", prefs.get("QuickPALM.viewer_do3d", false));
		//gd.addCheckbox("Make movie", prefs.get("QuickPALM.viewer_doMovie", false));
		gd.addCheckbox("Make 3D stack", false);
		gd.addCheckbox("Make movie", false);
		//gd.addCheckbox("Save only and don't show", prefs.get("QuickPALM.viewer_doSave", false));
		gd.addMessage("\n");

		// -----------------------------------------
		gd.addMessage("-- Simulate sub-difraction spot settings (used only if selected) --");
		gd.addNumericField("FWHM of the spot", prefs.get("QuickPALM.viewer_fwhm", 30), 2);
		gd.addMessage("\n");

		// -----------------------------------------
		gd.addMessage("-- Make 3D stack settings (used only if selected) --");
		gd.addNumericField("Z-spacing between slices (nm)", prefs.get("QuickPALM.viewer_zstep", 50), 2);
		gd.addNumericField("Merge particle Z-position above (nm - 0 for full Z range)", prefs.get("QuickPALM.viewer_mergeabove", 0), 2);
		gd.addNumericField("Merge particle Z-position bellow (nm - 0 for full Z range)",prefs.get("QuickPALM.viewer_mergebellow", 0), 2);
		gd.addMessage("\n");

		// -----------------------------------------
		gd.addMessage("-- Make movie settings (used only if selected) --");
		gd.addNumericField("Make a reconstruction in every N frames", prefs.get("QuickPALM.viewer_update", 10), 0);
		gd.addNumericField("Accumulate N neighboring frames for each reconstruction\n(set to 0 to accumulate all the preceding frames)", prefs.get("QuickPALM.viewer_accumulate", 100), 0);

		gd.addMessage("-- Multicolor settings (used only if selected) --");
		gd.addNumericField("Number of colors (for multicolor image)", prefs.get("QuickPALM.Colors", 1), 0);

		gd.addMessage("-- Custom colors (used only if selected--)");
		gd.addNumericField("Red value", prefs.get("QuickPALM.redValue", 77), 0);
		gd.addNumericField("Green value", prefs.get("QuickPALM.greenValue", 77), 0);
		gd.addNumericField("Blue value", prefs.get("QuickPALM.blueValue", 77), 0);

		gd.showDialog();
		if (gd.wasCanceled())
			return false;

		viewer_tpixelsize = gd.getNextNumber();
		prefs.set("QuickPALM.viewer_tpixelsize", viewer_tpixelsize );
		viewer_owidth = (int) gd.getNextNumber();
		prefs.set("QuickPALM.viewer_owidth", viewer_owidth);
		viewer_oheight = (int) gd.getNextNumber();
		prefs.set("QuickPALM.viewer_oheight", viewer_oheight);
		view_mode = gd.getNextChoice();
		prefs.set("QuickPALM.view_mode", view_mode);

		viewer_doConvolve = gd.getNextBoolean();
		prefs.set("QuickPALM.viewer_doConvolve", viewer_doConvolve);
		viewer_do3d = gd.getNextBoolean();
		prefs.set("QuickPALM.viewer_do3d", viewer_do3d);
		viewer_doMovie = gd.getNextBoolean();
		prefs.set("QuickPALM.viewer_doMovie", viewer_doMovie);
		//viewer_doSave = gd.getNextBoolean();
		//prefs.set("QuickPALM.viewer_doSave", viewer_doSave);

		// -- Simulate sub-difraction spot
		viewer_fwhm = gd.getNextNumber();
		prefs.set("QuickPALM.viewer_fwhm", viewer_fwhm);

		// -- Show B&W
		//viewer_is8bit = gd.getNextBoolean();
		//prefs.set("QuickPALM.viewer_is8bit", viewer_is8bit);

		// -- Make 3D stack
		viewer_zstep = gd.getNextNumber();
		prefs.set("QuickPALM.viewer_zstep", viewer_zstep);
		viewer_mergeabove = gd.getNextNumber();
		prefs.set("QuickPALM.viewer_mergeabove", viewer_mergeabove);
		viewer_mergebellow = gd.getNextNumber();
		prefs.set("QuickPALM.viewer_mergebellow", viewer_mergebellow);

		// -- Make Movie
		viewer_update = (int) gd.getNextNumber();
		prefs.set("QuickPALM.viewer_update", viewer_update);
		viewer_accumulate = (int) gd.getNextNumber();
		prefs.set("QuickPALM.viewer_accumulate", viewer_accumulate);

		// Multicolor
		Colors = (int) gd.getNextNumber();
		prefs.set("QuickPALM.Colors", Colors);

		// Custom color
		redValue = gd.getNextNumber();
		prefs.set("QuickPALM.redValue", redValue);
		greenValue = gd.getNextNumber();
		prefs.set("QuickPALM.greenValue", greenValue);
		blueValue = gd.getNextNumber();
		prefs.set("QuickPALM.blueValue", blueValue);

		return true;
	}

	public boolean loadReconstructDataset()
	{
		view_modes[0]="3D color";
		view_modes[1]="2D histogram";
		view_modes[2]="2D particle intensity (16-bit)";
		view_modes[3]="2D particle intensity (8-bit)";
		view_modes[4]="2D multicolor";
		view_modes[5]="custom colors";


		viewer_tpixelsize = prefs.get("QuickPALM.viewer_tpixelsize", 30);
		viewer_owidth = (int) prefs.get("QuickPALM.viewer_owidth", 512);
		viewer_oheight = (int) prefs.get("QuickPALM.viewer_oheight", 512);
		view_mode = prefs.get("QuickPALM.view_mode", view_modes[1]);

		viewer_doConvolve = prefs.get("QuickPALM.viewer_doConvolve", true);
		viewer_do3d = prefs.get("QuickPALM.viewer_do3d", false);
		viewer_doMovie = prefs.get("QuickPALM.viewer_doMovie", false);
		viewer_fwhm = prefs.get("QuickPALM.viewer_fwhm", 30);

		viewer_zstep = prefs.get("QuickPALM.viewer_zstep", 50);
		viewer_mergeabove = prefs.get("QuickPALM.viewer_mergeabove", 0);
		viewer_mergebellow = prefs.get("QuickPALM.viewer_mergebellow", 0);

		viewer_update = (int) prefs.get("QuickPALM.viewer_update", 10);
		viewer_accumulate = (int) prefs.get("QuickPALM.viewer_accumulate", 0);
		Colors = (int) prefs.get("QuickPALM.Colors", 1);
		redValue = prefs.get("QuickPALM.redValue", 77);
		greenValue = prefs.get("QuickPALM.greenValue", 77);
		blueValue = prefs.get("QuickPALM.blueValue", 77);
		return true;
	}


	// Changed analyseParticles() into writeAnalyseParticles()
	public boolean writeAnalyseParticles() {	
		GenericDialog gd = new GenericDialog("Analyse PALM/STORM Particles");
		gd.addNumericField("EM Gain", prefs.get("QuickPALM.EMGain", 1), 2);
		gd.addNumericField("Pre-amplifier Gain", prefs.get("QuickPALM.preAmp", 5.1), 2);
		gd.addNumericField("Minimum SNR", prefs.get("QuickPALM.snr", 5), 2); 
		gd.addNumericField("Maximum FWHM (in px)", prefs.get("QuickPALM.fwhm", 4), 0);
		gd.addNumericField("Image plane pixel size (nm)", prefs.get("QuickPALM.pixelsize", 160), 2);
		gd.addCheckbox("Smart SNR", prefs.get("QuickPALM.smartsnr", true));
		gd.addCheckbox("3D STORM (astigmatism) - will require calibration file", prefs.get("QuickPALM.is3d", false));
		gd.addCheckbox("Online rendering", prefs.get("QuickPALM.view", true));
		gd.addCheckbox("Attach to running acquisition", prefs.get("QuickPALM.attach", false));
		gd.addCheckbox("Stream particle info directly into file", prefs.get("QuickPALM.stream", true));
		gd.addMessage("\n");
		// -----------------------------------------
		gd.addMessage("-- Online rendering settings (used only if selected) --");
		gd.addMessage("\n");
		gd.addNumericField("Pixel size of rendered image (nm)", 30, 2);
		gd.addNumericField("Accumulate last (0 to accumulate all frames)", 0, 0);
		gd.addNumericField("Update every (frames)", 10, 0);
		//gd.addNumericField("Allow color saturation (%)", 50, 0);
		gd.addMessage("\n");
		// -----------------------------------------
		gd.addMessage("-- Attach to running acquisition settings (used only if selected) --");
		gd.addMessage("\n");
		gd.addStringField("_Image name pattern (NN...NN represents the numerical change)", prefs.get("QuickPALM.pattern", "imgNNNNNNNNN.tif"), 20);
		gd.addNumericField("Start NN...NN with", 0, 0);
		gd.addNumericField("In acquisition max. wait time for new image (ms)", 50, 0);
		gd.addMessage("\n");
		// -----------------------------------------
		gd.addMessage("-- Advanced settings (don't normally need to be changed) --");
		gd.addMessage("\n");
		gd.addNumericField("_Minimum symmetry (%)", prefs.get("QuickPALM.symmetry", 50), 0);
		gd.addNumericField("Local threshold (% maximum intensity)", prefs.get("QuickPALM.lthreshold", 20), 0);
		gd.addNumericField("_Maximum iterations per frame", prefs.get("QuickPALM.maxpart", 1000), 0);
		gd.addNumericField("Threads (each takes ~3*[frame size] in memory)", prefs.get("QuickPALM.threads", 50), 0);

		gd.addCheckbox("Multicolor", prefs.get("QuickPALM.Multicolor", false));
		gd.addNumericField("How many colors?", prefs.get("QuickPALM.Colors", 1), 0);

		gd.showDialog();
		if (gd.wasCanceled())
			return false;

		EMGain = (int)gd.getNextNumber();
		prefs.set("QuickPALM.EMGain", EMGain);
		preAmp = gd.getNextNumber();
		prefs.set("QuickPALM.preAmp", preAmp);
		snr = (int)gd.getNextNumber();
		prefs.set("QuickPALM.snr", snr);
		fwhm = gd.getNextNumber();
		prefs.set("QuickPALM.fwhm", fwhm);
		pixelsize = gd.getNextNumber();
		prefs.set("QuickPALM.pixelsize", pixelsize);
		smartsnr = gd.getNextBoolean();
		prefs.set("QuickPALM.smartsnr", smartsnr);
		is3d = gd.getNextBoolean();
		prefs.set("QuickPALM.is3d", is3d);
		view = gd.getNextBoolean();
		prefs.set("QuickPALM.view", view);
		attach = gd.getNextBoolean();
		prefs.set("QuickPALM.attach", attach);
		saveToFile = gd.getNextBoolean();
		prefs.set("QuickPALM.stream", saveToFile);

		RImagePSize = gd.getNextNumber();
		prefs.set("QuickPALM.RImagePSize", RImagePSize);
		viewer_accumulate = (int) gd.getNextNumber();
		prefs.set("QuickPALM.viewer_accumulate", viewer_accumulate);
		viewer_update = (int) gd.getNextNumber();
		prefs.set("QuickPALM.viewer_update", viewer_update);

		pattern = gd.getNextString();
		prefs.set("QuickPALM.pattern", pattern);
		nimstart = (int) gd.getNextNumber();
		prefs.set("QuickPALM.nimstart", nimstart);
		waittime = (int) gd.getNextNumber();
		prefs.set("QuickPALM.waittime", waittime);

		symmetry = gd.getNextNumber()/100;
		prefs.set("QuickPALM.symmetry", symmetry*100);
		pthrsh = gd.getNextNumber()/100;
		prefs.set("QuiclPALM.lthreshold", pthrsh*100);
		maxpart = (int) gd.getNextNumber();
		prefs.set("quickPALM.maxpart", maxpart);
		threads = (int) gd.getNextNumber();
		prefs.set("QuickPALM.threads", threads);

		Multicolor = gd.getNextBoolean();
		prefs.set("QuickPALM.Multicolor", Multicolor);
		Colors = (int) gd.getNextNumber();
		prefs.set("QuickPALM.Colors", Colors);


		return true;
	}

	public boolean loadAnalyseParticles()
	{
		EMGain = (int) prefs.get("QuickPALM.EMGain", 1);
		preAmp = prefs.get("QuickPALM.preAmp", 5.1);
		snr = (int) prefs.get("QuickPALM.snr", 5);
		fwhm = prefs.get("QuickPALM.fwhm", 4); 
		pixelsize = prefs.get("QuickPALM.pixelsize", 106);

		smartsnr = prefs.get("QuickPALM.smartsnr", true); 
		is3d = prefs.get("QuickPALM.is3d", false); 
		view = prefs.get("QuickPALM.view", true); 
		attach = prefs.get("QuickPALM.attach", false); 
		saveToFile = prefs.get("QuickPALM.stream", true); 
		//--

		RImagePSize = prefs.get("QuickPALM.RImagePSize", 30); 
		magn = pixelsize/RImagePSize; 
		viewer_accumulate = (int) prefs.get("QuickPALM.viewer_accumulate", 0);
		viewer_update = (int) prefs.get("QuickPALM.viewer_update", 10);

		//--
		pattern = prefs.get("QuickPALM.pattern", "imgNNNNNNNNN.tif"); // rd.readLine(); // Image name pattern
		prefix = pattern.substring(0, pattern.indexOf("N"));
		sufix = pattern.substring(pattern.lastIndexOf("N")+1, pattern.length());
		nimchars = pattern.split("N").length-1;
		nimstart = (int) prefs.get("QuickPALM.nimstart", 0); // (int) D4;
		waittime = (int) prefs.get("QuickPALM.waittime", 50); // (int) D5;

		//--

		symmetry = prefs.get("QuickPALM.symmetry", 50)/100; 
		pthrsh = prefs.get("QuickPALM.lthreshold", 20)/100; 
		maxpart = (int) prefs.get("QuickPALM.maxpart", 1000); // (int) D6;
		threads = (int) prefs.get("QuickPALM.threads", 50); // (int) D7;
		Multicolor = prefs.get("QuickPALM.Multicolor", false);
		Colors = (int) prefs.get("QuickPALM.Colors", 1);

		return true;
	}

	public boolean writeSimConfig()
	{
		GenericDialog gd = new GenericDialog("Simulator settings");

		// gd.addCheckbox("Classic optical image", prefs.get("QuickPALM.sim_climg", true));
		gd.addCheckbox("Open sample image from files", false);
		gd.addNumericField("Width in pixels", prefs.get("QuickPALM.drawer_owidth", 512), 2);
		gd.addNumericField("Height in pixels", prefs.get("QuickPALM.drawer_oheight", 512), 2);
		gd.addNumericField("CCD pixelsize (in micrometers)", prefs.get("QuickPALM.drawer_psize", 16), 2);
		gd.addNumericField("System magnification", prefs.get("QuickPALM.drawer_magn", 100), 2);
		gd.addNumericField("Numeric aperture", prefs.get("QuickPALM.drawer_NA", 1.49), 2);
		gd.addNumericField("Sample pixelsize (nm)", prefs.get("QuickPALM.drawer_minpsize", 20), 2);

		gd.addMessage("----------------");
		gd.addNumericField("Activation probability factor", prefs.get("QuickPALM.drawer_intensity", 5), 2);
		gd.addNumericField("Average photon number", prefs.get("QuickPALM.drawer_max", 1000), 2);
		gd.addNumericField("Deviation of photon number", prefs.get("QuickPALM.drawer_peakdev", 100), 2);
		gd.addNumericField("Noise factor", prefs.get("QuickPALM.drawer_noise", 1), 2);
		gd.addNumericField("Maximum frame number", prefs.get("QuickPALM.drawer_nframe", 1000), 0);

		gd.addMessage("----------------");
		gd.addNumericField("Minimum SNR", prefs.get("QuickPALM.snr", 5), 2);
		gd.addCheckbox("Customize FWHM(in px)", false);
		gd.addNumericField("Maximum FWHM (in px)", prefs.get("QuickPALM.fwhm", 4), 0);
		// gd.addNumericField("Image plane pixel size (nm)", prefs.get("QuickPALM.pixelsize", 160), 2);

		gd.addMessage("----------------");
		gd.addNumericField("Pixel size of rendered image (nm)", prefs.get("QuickPALM.RImagePSize", 10), 2);
		gd.addNumericField("Accumulate last (0 to accumulate all frames)", 0, 0);
		gd.addNumericField("Update every (frames)", 10, 0);

		gd.addMessage("----------------");
		gd.addNumericField("Target pixel size for the rendered image(nm)", prefs.get("QuickPALM.viewer_tpixelsize", 10), 2);
		gd.addNumericField("In take image width", prefs.get("QuickPALM.viewer_owidth", 64), 2);
		gd.addNumericField("In take image height", prefs.get("QuickPALM.viewer_oheight", 64), 2);
		gd.addCheckbox("Gaussian convolution", prefs.get("QuickPALM.viewer_doConvolve", true));
		gd.addNumericField("FWHM of the spot", prefs.get("QuickPALM.viewer_fwhm", 10), 2);

		gd.showDialog();
		if (gd.wasCanceled())
			return false;

		// sim_climg = gd.getNextBoolean();
		// prefs.set("QuickPALM.sim_climg", sim_climg);
		sim_open = gd.getNextBoolean();
		prefs.set("QuickPALM.sim_open", sim_open);
		drawer_owidth = (int) gd.getNextNumber();
		prefs.set("QuickPALM.drawer_owidth", drawer_owidth);
		drawer_oheight = (int) gd.getNextNumber();
		prefs.set("QuickPALM.drawer_oheight", drawer_oheight);
		drawer_psize = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_psize", drawer_psize);
		drawer_magn = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_magn", drawer_magn);
		drawer_NA = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_NA", drawer_NA);
		drawer_minpsize = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_minpsize", drawer_minpsize);

		drawer_intensity = gd.getNextNumber() / 10000;
		prefs.set("QuickPALM.drawer_intensity", drawer_intensity * 10000);
		drawer_max = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_max", drawer_max);
		drawer_peakdev = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_peakdev", drawer_peakdev);
		drawer_noise = gd.getNextNumber() / 100;
		prefs.set("QuickPALM.drawer_noise", drawer_noise * 100);
		drawer_nframe = (int) gd.getNextNumber();
		prefs.set("QuickPALM.drawer_nframe", drawer_nframe);

		snr = (int)gd.getNextNumber();
		prefs.set("QuickPALM.snr", snr);
		cusfwhm = gd.getNextBoolean();
		prefs.set("QuickPALM.cusfwhm", cusfwhm);
		fwhm = gd.getNextNumber();
		prefs.set("QuickPALM.fwhm", fwhm);
		// pixelsize = gd.getNextNumber();
		// prefs.set("QuickPALM.pixelsize", pixelsize);

		RImagePSize = gd.getNextNumber();
		prefs.set("QuickPALM.RImagePSize", RImagePSize);
		viewer_accumulate = (int) gd.getNextNumber();
		prefs.set("QuickPALM.viewer_accumulate", viewer_accumulate);
		viewer_update = (int) gd.getNextNumber();
		prefs.set("QuickPALM.viewer_update", viewer_update);

		viewer_tpixelsize = gd.getNextNumber();
		prefs.set("QuickPALM.viewer_tpixelsize", viewer_tpixelsize);
		viewer_owidth = (int)gd.getNextNumber();
		prefs.set("QuickPALM.viewer_owidth", viewer_owidth);
		viewer_oheight = (int)gd.getNextNumber();
		prefs.set("QuickPALM.viewer_oheight", viewer_oheight);
		viewer_doConvolve = gd.getNextBoolean();
		prefs.set("QuickPALM.viewer_doConvolve", viewer_doConvolve);
		viewer_fwhm = gd.getNextNumber();
		prefs.set("QuickPALM.viewer_fwhm", viewer_fwhm);

		return true;
	}

	public boolean loadSimConfig()
	{
		// sim_climg = prefs.get("QuickPALM.sim_climg", true);
		sim_open = prefs.get("QuickPALM.sim_open", false);
		drawer_owidth = (int) prefs.get("QuickPALM.drawer_owidth", 64);
		drawer_oheight = (int) prefs.get("QuickPALM.drawer_oheight", 64);
		drawer_psize = prefs.get("QuickPALM.drawer_psize", 16);
		drawer_magn = prefs.get("QuickPALM.drawer_magn", 200);
		drawer_NA = prefs.get("QuickPALM.drawer_NA", 1.49);
		drawer_minpsize = prefs.get("QuickPALM.drawer_minpsize", 10);

		drawer_intensity = prefs.get("QuickPALM.drawer_intensity", 50) / 10000;
		drawer_max = prefs.get("QuickPALM.drawer_max", 1000);
		drawer_peakdev = prefs.get("QuickPALM.drawer_peakdev", 100);
		drawer_noise = prefs.get("QuickPALM.drawer_noise", 1) / 100;
		drawer_nframe = (int) prefs.get("QuickPALM.drawer_nframe", 10000);

		snr = (int) prefs.get("QuickPALM.snr", 5);
		if (cusfwhm)
			fwhm = prefs.get("QuickPALM.fwhm", 4);
		else
			fwhm = 0.5 * 656.5 * drawer_magn / (drawer_NA * drawer_psize * 1000);
		pixelsize = drawer_psize * 1000 / drawer_magn;
		// pixelsize = prefs.get("QuickPALM.pixelsize", 106);

		RImagePSize = prefs.get("QuickPALM.RImagePSize", 30);
		magn = pixelsize/RImagePSize;
		viewer_accumulate = (int) prefs.get("QuickPALM.viewer_accumulate", 0);
		viewer_update = (int) prefs.get("QuickPALM.viewer_update", 10);

		viewer_tpixelsize = prefs.get("QuickPALM.viewer_tpixelsize", 10);
		viewer_owidth = (int) prefs.get("QuickPALM.viewer_owidth", 64);
		viewer_oheight = (int) prefs.get("QuickPALM.viewer_oheight", 64);
		viewer_doConvolve = prefs.get("QuickPALM.viewer_doConvolve", false);
		viewer_fwhm = prefs.get("QuickPALM.viewer_fwhm", 10);

		return true;
	}

	public boolean testConfig()
	{
		sim_objs[0] = "Single particle";
		sim_objs[1] = "Double particle";

		GenericDialog gd = new GenericDialog("Simulator settings");
		gd.addChoice("Select object", sim_objs, prefs.get("QuickPALM.sim_obj", sim_objs[0]));
		gd.addNumericField("Sample pixel size(nm)", prefs.get("QuickPALM.sim_minpsize", 10), 2);	
		gd.addNumericField("Camera pixel size(micrometers)", prefs.get("QuickPALM.sim_campsize", 16), 2);	
		gd.addNumericField("Width (px)", prefs.get("QuickPALM.sim_clwidth", 64), 0);
		gd.addNumericField("Height (px)", prefs.get("QuickPALM.sim_clheight", 64), 0);
		gd.addNumericField("System magnification", prefs.get("QuickPALM.sim_magn", 100), 0);	
		gd.addNumericField("Numeric aperture", prefs.get("QuickPALM.drawer_NA", 1.49), 2);
		gd.addNumericField("Activation probability(%)(for point objects)", prefs.get("QuickPALM.sim_prob", 50), 0);
		gd.addNumericField("Object distance(nm) (For dual objects)", prefs.get("QuickPALM.sim_dis", 20), 2);
		gd.addMessage("--------------------");

		gd.addNumericField("Maximum number of frames", prefs.get("QuickPALM.drawer_nframe", 1000), 0);
		gd.addNumericField("Noise factor", prefs.get("QuickPALM.drawer_noise", 1), 2);
		gd.addCheckbox("Customize radius", prefs.get("QuickPALM.test_cusr", false));
		gd.addNumericField("Average radius spot radius (pixel)", prefs.get("QuickPALM.drawer_radius", 3), 2);

		gd.showDialog();
		if (gd.wasCanceled())
			return false;

		sim_obj = gd.getNextChoice();
		prefs.set("QuickPALM.sim_obj", sim_obj);
		sim_minpsize = gd.getNextNumber();
		prefs.set("QuickPALM.sim_minpsize", sim_minpsize);
		sim_campsize = gd.getNextNumber();
		prefs.set("QuickPALM.sim_campsize", sim_campsize);
		sim_clwidth = (int)gd.getNextNumber();
		prefs.set("QuickPALM.sim_clwidth", sim_clwidth);
		sim_clheight = (int)gd.getNextNumber();
		prefs.set("QuickPALM.sim_clheight", sim_clheight);
		sim_magn = gd.getNextNumber();
		prefs.set("QuickPALM.sim_magn", sim_magn);
		drawer_NA = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_NA", drawer_NA);
		sim_prob = gd.getNextNumber()/100;
		prefs.set("QuickPALM.sim_prob", sim_prob*100);
		sim_dis = gd.getNextNumber();
		prefs.set("QuickPALM.sim_dis", sim_dis);

		drawer_nframe = (int) gd.getNextNumber();
		prefs.set("QuickPALM.drawer_nframe", drawer_nframe);
		drawer_noise = gd.getNextNumber() / 100;
		prefs.set("QuickPALM.drawer_noise", drawer_noise * 100);

		if (gd.getNextBoolean())
		{
			drawer_radius = gd.getNextNumber();
			prefs.set("QuickPALM.drawer_radius", drawer_radius);
		}
		else
			drawer_radius = 0.61*656.5*sim_magn/(drawer_NA*sim_campsize*1000);

		return true;
	}



	public boolean drawer()
	{
		sim_modes[0] = "Classic mode";
		sim_modes[1] = "Virtual experiment mode";

		sim_objs[0] = "Single particle";
		sim_objs[1] = "Double particle";
		sim_objs[2] = "Double line";
		sim_objs[3] = "Multiple particles";
		sim_objs[4] = "Multiple lines";

		drawer_modes[0] = "2D STORM";
		drawer_modes[1] = "3D STORM";

		GenericDialog gd = new GenericDialog("Simulator settings");

		gd.addChoice("Simulator mode", sim_modes, prefs.get("QuickPALM.sim_mode", sim_modes[0]));

		gd.addMessage("Classic mode:");
		gd.addChoice("Select object", sim_objs, prefs.get("QuickPALM.sim_obj", sim_objs[0]));
		gd.addNumericField("Sample pixel size(nm)", prefs.get("QuickPALM.sim_minpsize", 10), 2);	
		gd.addNumericField("Camera pixel size(micrometers)", prefs.get("QuickPALM.sim_campsize", 16), 2);	
		gd.addNumericField("Width (px)", prefs.get("QuickPALM.sim_clwidth", 512), 0);
		gd.addNumericField("Height (px)", prefs.get("QuickPALM.sim_clheight", 512), 0);
		gd.addNumericField("System magnification", prefs.get("QuickPALM.sim_magn", 100), 0);	
		gd.addNumericField("Activation probability(%)(for point objects)", prefs.get("QuickPALM.sim_prob", 50), 0);
		gd.addNumericField("Object distance(nm) (For dual objects)", prefs.get("QuickPALM.sim_dis", 20), 2);
		gd.addNumericField("Object minimum distance(nm) (For multiple objects)", prefs.get("QuickPALM.sim_mindis", 5), 2);

		gd.addMessage("Virtual experiment mode:");
		gd.addCheckbox("Classic optical image", prefs.get("QuickPALM.sim_climg", true));
		gd.addCheckbox("Open sample image from files", false);
		gd.addChoice("Work mode", drawer_modes, prefs.get("QuickPALM.drawer_mode", drawer_modes[0]));
		gd.addNumericField("Width in pixels", prefs.get("QuickPALM.drawer_owidth", 512), 2);
		gd.addNumericField("Height in pixels", prefs.get("QuickPALM.drawer_oheight", 512), 2);
		gd.addCheckbox("Customize sample resolution(effective pixelsize)", false);
		gd.addNumericField("Effective minimum pixelsize (nm)", prefs.get("QuickPALM.drawer_minpsize", 20), 2);
		gd.addNumericField("CCD pixelsize (in micrometers)", prefs.get("QuickPALM.drawer_psize", 16), 2);
		gd.addNumericField("System magnification", prefs.get("QuickPALM.drawer_magn", 100), 2);

		gd.addMessage("Drawer settings");
		gd.addNumericField("Activation probability factor", prefs.get("QuickPALM.drawer_intensity", 5), 2);
		gd.addNumericField("Number of frames", prefs.get("QuickPALM.drawer_nframe", 1000), 0);
		gd.addNumericField("Photon number factor (related to the intensity of the florescent LASER)", prefs.get("QuickPALM.drawer_max", 120), 2);
		gd.addNumericField("Deviation of photon number", prefs.get("QuickPALM.drawer_peakdev", 15), 2);
		gd.addNumericField("Noise factor", prefs.get("QuickPALM.drawer_noise", 1), 2);
		// gd.addNumericField("Center (0 ~ 1)", prefs.get("QuickPALM.sim_center", 0.5), 2);
		gd.addNumericField("Average radius spot radius (pixel)", prefs.get("QuickPALM.drawer_radius", 4), 2);

		gd.showDialog();
		if (gd.wasCanceled())
			return false;

		sim_mode = gd.getNextChoice();
		prefs.set("QuickPALM.sim_mode", sim_mode);

		// Classic mode
		sim_obj = gd.getNextChoice();
		prefs.set("QuickPALM.sim_obj", sim_obj);
		sim_minpsize = gd.getNextNumber();
		prefs.set("QuickPALM.sim_minpsize", sim_minpsize);
		sim_campsize = gd.getNextNumber();
		prefs.set("QuickPALM.sim_campsize", sim_campsize);
		sim_clwidth = (int)gd.getNextNumber();
		prefs.set("QuickPALM.sim_clwidth", sim_clwidth);
		sim_clheight = (int)gd.getNextNumber();
		prefs.set("QuickPALM.sim_clheight", sim_clheight);
		sim_magn = gd.getNextNumber();
		prefs.set("QuickPALM.sim_magn", sim_magn);
		sim_prob = gd.getNextNumber()/100;
		prefs.set("QuickPALM.sim_prob", sim_prob*100);
		sim_dis = gd.getNextNumber();
		prefs.set("QuickPALM.sim_dis", sim_dis);
		sim_mindis = gd.getNextNumber();
		prefs.set("QuickPALM.sim_mindis", sim_mindis);

		// VE mode
		sim_climg = gd.getNextBoolean();
		prefs.set("QuickPALM.sim_climg", sim_climg);
		sim_open = gd.getNextBoolean();
		drawer_mode = gd.getNextChoice();
		prefs.set("QuickPALM.drawer_mode", drawer_mode);
		drawer_owidth = (int) gd.getNextNumber();
		prefs.set("QuickPALM.drawer_owidth", drawer_owidth);
		drawer_oheight = (int) gd.getNextNumber();
		prefs.set("QuickPALM.drawer_oheight", drawer_oheight);
		drawer_cusres = gd.getNextBoolean();
		drawer_minpsize = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_minpsize", drawer_minpsize);
		drawer_psize = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_psize", drawer_psize);
		drawer_magn = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_magn", drawer_magn);

		// Stack generator settings
		drawer_intensity = gd.getNextNumber() / 10000;
		prefs.set("QuickPALM.drawer_intensity", drawer_intensity * 10000);
		drawer_nframe = (int) gd.getNextNumber();
		prefs.set("QuickPALM.drawer_nframe", drawer_nframe);
		drawer_max = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_max", drawer_max);
		drawer_peakdev = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_peakdev", drawer_peakdev);
		drawer_noise = gd.getNextNumber() / 100;
		prefs.set("QuickPALM.drawer_noise", drawer_noise * 100);
		drawer_radius = gd.getNextNumber();
		prefs.set("QuickPALM.drawer_radius", drawer_radius);

		return true;
	}

	/*public boolean simulator()
		{
		sim_modes[0] = "Circle";
		sim_modes[1] = "Ellipse";
		sim_modes[2] = "Random spot";

		GenericDialog gd = new GenericDialog("Simulator settings");

		gd.addChoice("Simulator mode", sim_modes, prefs.get("QuickPALM.sim_mode", sim_modes[0]));
		gd.addNumericField("Intensity(%)", prefs.get("QuickPALM.sim_intensity", 5), 2);
		gd.addNumericField("Number of frames", prefs.get("QuickPALM.sim_nframe", 1000), 0);
		gd.addNumericField("Maximum intensity", prefs.get("QuickPALM.sim_max", 120), 2);
		gd.addNumericField("Deviation of the peak value", prefs.get("QuickPALM.sim_peakdev", 15), 2);
		gd.addNumericField("Average radius of the spot", prefs.get("QuickPALM.sim_radius", 3), 2);
		gd.addNumericField("Noise level(%)", prefs.get("QuickPALM.sim_noise", 10), 2);

		gd.showDialog();
		if (gd.wasCanceled())
		return false;

		sim_mode = gd.getNextChoice();
		prefs.set("QuickPALM.sim_mode", sim_mode);
		sim_intensity = gd.getNextNumber() / 100;
		prefs.set("QuickPALM.sim_intensity", sim_intensity * 100);
		sim_nframe = (int) gd.getNextNumber();
		prefs.set("QuickPALM.sim_nframe", sim_nframe);
		sim_max = gd.getNextNumber();
		prefs.set("QuickPALM.sim_max", sim_max);
		sim_peakdev = gd.getNextNumber();
		prefs.set("QuickPALM.sim_peakdev", sim_peakdev);
		sim_radius = (int) gd.getNextNumber();
		prefs.set("QuickPALM.sim_radius", sim_radius);
		sim_noise = gd.getNextNumber() / 100;
		prefs.set("QuickPALM.sim_noise", sim_noise * 100);

		return true;
		}*/
}
